package com.hexacta.hrs.web.struts.actions.feedbacks;

import java.awt.Color;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;

import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.xssf.usermodel.XSSFCellStyle;
import org.apache.poi.xssf.usermodel.XSSFColor;
import org.apache.poi.xssf.usermodel.XSSFFont;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.apache.struts2.interceptor.ServletRequestAware;
import org.apache.struts2.interceptor.SessionAware;
import org.vectrics.employee.Employee;
import org.vectrics.provider.CoreServiceLocator;
import org.vectrics.user.Person;

import com.hexacta.hrs.domain.feedback.ArchivoAdjunto;
import com.hexacta.hrs.domain.feedback.FeedbackMentorEffortScore;
import com.hexacta.hrs.domain.feedback.FeedbackMentorSkill;
import com.hexacta.hrs.domain.feedback.FeedbackMentorsProsAndCons;
import com.hexacta.hrs.domain.feedback.FeedbackPeriod;
import com.hexacta.hrs.domain.feedback.FeedbackPeriodMentorReport;
import com.hexacta.hrs.securitygroups.PermissionName;
import com.hexacta.hrs.services.feedbacks.FeedbackPeriodService;
import com.hexacta.hrs.services.feedbacks.PeriodService;
import com.hexacta.hrs.services.mentoring.MentoringService;
import com.hexacta.hrs.web.struts.actions.security.PermissionChecker;
import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionSupport;

public class MentorsHistoricReportAction extends ActionSupport implements SessionAware, ServletRequestAware {

    private static final long serialVersionUID = 1L;

    private static String EXCEL = "excel";

    private String AUTOEVALUATION = "autoevaluation";

    private FeedbackPeriodService feedbackPeriodService;

    private PeriodService periodService;

    private MentoringService mentoringService;

    private PermissionChecker permissionChecker = new PermissionChecker();

    private Map<String, Object> session;

    private Person user;

    private long selectedMentorId;

    private String selectedMentorName;

    private String periodId;

    private InputStream autoevaluationStream;

    private InputStream excelStream;

    private String fileName;

    private HttpServletRequest request;

    private Collection<FeedbackPeriodMentorReport> mentorsReportList = new ArrayList<FeedbackPeriodMentorReport>();

    /**
     * Devuelve, en caso de que posea, la autoevaluaci�n de un mentorado, para
     * un periodo dado.
     * 
     * @return Serlf-Evaluation
     */
    public String downloadAutoevaluation() {
        Object feedbackId = ActionContext.getContext().getParameters().get("feedbackId");
        Long id = Long.valueOf(((String[]) feedbackId)[0]);
        FeedbackPeriod period = feedbackPeriodService.findById(id);

        ArchivoAdjunto autoevaluation = period.getSelfevaluation();

        if (autoevaluation == null) {
            addFieldError("feebackId", "Employee has no self-evaluation for this period");
            return INPUT;
        }

        autoevaluationStream = new ByteArrayInputStream(autoevaluation.getBytes());
        fileName = autoevaluation.getNombre();

        return AUTOEVALUATION;
    }

    /**
     * Genera el reporte mentor en formato xlsx
     * 
     */
    public String excelStream() throws IOException, Exception {
        if (getSelectedMentorName() == null || getSelectedMentorName().trim().equals("")){
            return INPUT;
        }

        XSSFWorkbook wb = new XSSFWorkbook();

        Sheet sheet = wb.createSheet("Mentor Report");

        Integer currentRow = 0;

        Row row = sheet.createRow(currentRow);

        sheet.setColumnWidth(0,30*256);
	    sheet.setColumnWidth(1,30*256);
	    sheet.setColumnWidth(2,50*256);
	    sheet.setColumnWidth(3,50*256);
	    sheet.setColumnWidth(4,2*256);

        Cell cellTittle = row.createCell(0);
        cellTittle.setCellStyle(getTittlesStyle(wb));
        cellTittle.setCellValue("Mentor: ");

        Cell cell = row.createCell(1);
        cell.setCellStyle(getHeadersStyle(wb));
        cell.setCellValue(getSelectedMentorName());
        currentRow++;
        for ( FeedbackPeriodMentorReport feedbackPeriodMentorReport : getMentorsReportList()) {
	    	Row rowHeader = sheet.createRow(currentRow+1);
	    	Cell cellTittleFeedback = rowHeader.createCell(0);
	    	cellTittleFeedback.setCellStyle(getTittlesStyle(wb));
	    	//Mentored
	    	cellTittleFeedback.setCellValue("Evaluated: ");
	    	Cell cellHeader = rowHeader.createCell(1);
	    	cellHeader.setCellStyle(getHeadersStyle(wb));
	    	cellHeader.setCellValue(feedbackPeriodMentorReport.getFeedbackPeriod().getEmployee().getPerson().getName());
	    	
	    	Cell cellExtra = rowHeader.createCell(2);
			cellExtra.setCellStyle(getExtraStyle(wb));
			cellExtra = rowHeader.createCell(3);
			cellExtra.setCellStyle(getExtraStyle(wb));
			cellExtra = rowHeader.createCell(4);
			cellExtra.setCellStyle(getExtraStyle(wb));
	    	//Job Function
	    	
	    	rowHeader = sheet.createRow(currentRow+2);
	    	cellTittleFeedback = rowHeader.createCell(0);
	    	cellTittleFeedback.setCellStyle(getTittlesStyle(wb));
	    	cellTittleFeedback.setCellValue("Role: ");

	    	cellHeader = rowHeader.createCell(1);
	    	cellHeader.setCellStyle(getHeadersStyle(wb));
	    	cellHeader.setCellValue(feedbackPeriodMentorReport.getFeedbackPeriod().getActualBand().getDescription());
	    	
	    	cellExtra = rowHeader.createCell(2);
			cellExtra.setCellStyle(getExtraStyle(wb));
			cellExtra = rowHeader.createCell(3);
			cellExtra.setCellStyle(getExtraStyle(wb));
			cellExtra = rowHeader.createCell(4);
			cellExtra.setCellStyle(getExtraStyle(wb));
			
	    	//Band
	    	rowHeader = sheet.createRow(currentRow+3);
	    	cellTittleFeedback = rowHeader.createCell(0);
	    	cellTittleFeedback.setCellStyle(getTittlesStyle(wb));
	    	cellTittleFeedback.setCellValue("Band: ");
	    	
	    	cellHeader = rowHeader.createCell(1);
	    	cellHeader.setCellStyle(getHeadersStyle(wb));
	    	cellHeader.setCellValue(feedbackPeriodMentorReport.getFeedbackPeriod().getActualPosition());
	    	
			cellExtra = rowHeader.createCell(2);
			cellExtra.setCellStyle(getExtraStyle(wb));
			cellExtra = rowHeader.createCell(3);
			cellExtra.setCellStyle(getExtraStyle(wb));
			cellExtra = rowHeader.createCell(4);
			cellExtra.setCellStyle(getExtraStyle(wb));
	    	currentRow+=4;	
		
	    	Row extraRow = sheet.createRow(currentRow);
	    	cellExtra = extraRow.createCell(0);
			cellExtra.setCellStyle(getExtraStyle(wb));
			cellExtra = extraRow.createCell(1);
			cellExtra.setCellStyle(getExtraStyle(wb));
			cellExtra = extraRow.createCell(2);
			cellExtra.setCellStyle(getExtraStyle(wb));
			cellExtra = extraRow.createCell(3);
			cellExtra.setCellStyle(getExtraStyle(wb));
			cellExtra = extraRow.createCell(4);
			cellExtra.setCellStyle(getExtraStyle(wb));
			
			currentRow+=1;
			
	    	for (FeedbackMentorSkill feedbackMentorSkill : feedbackPeriodMentorReport.getFeedbackMentorSkill()) {
	    		Row rowSkills = sheet.createRow(currentRow);
				
				Cell cellTittleSkill = rowSkills.createCell(2);//Tercer Fila
				cellTittleSkill.setCellStyle(getTittlesStyle(wb));
				cellTittleSkill.setCellValue(feedbackMentorSkill.getFeedbackSkillType().toString()); //el SkillType
				
				cellExtra = rowSkills.createCell(0);
				cellExtra.setCellStyle(getExtraStyle(wb));
				cellExtra = rowSkills.createCell(1);
				cellExtra.setCellStyle(getExtraStyle(wb));
				cellExtra = rowSkills.createCell(3);
				cellExtra.setCellStyle(getExtraStyle(wb));
				cellExtra = rowSkills.createCell(4);
				cellExtra.setCellStyle(getExtraStyle(wb));
				
					rowSkills = sheet.createRow(currentRow+1);
					Cell cellTittleFB = rowSkills.createCell(0);
					cellTittleFB.setCellStyle(getDataStyle(wb));
					cellTittleFB.setCellValue("Evaluator ");
					
					cellTittleFB = rowSkills.createCell(1);
					cellTittleFB.setCellStyle(getTittlesStyle(wb));
					cellTittleFB.setCellValue("Project ");

					cellTittleFB = rowSkills.createCell(2);
					cellTittleFB.setCellStyle(getTittlesStyle(wb));
					cellTittleFB.setCellValue("Pros: ");
					
					cellTittleFB = rowSkills.createCell(3);
					cellTittleFB.setCellStyle(getTittlesStyle(wb));
					cellTittleFB.setCellValue("Cons: ");
					
					cellExtra = rowSkills.createCell(4);
					cellExtra.setCellStyle(getExtraStyle(wb));
					
					currentRow+=2;
					
					for (FeedbackMentorsProsAndCons prosAndCons : feedbackMentorSkill.getFeedbackMentorsProsAndCons()) {
						rowSkills = sheet.createRow(currentRow);
						Cell cellSkills = rowSkills.createCell(0);
						cellSkills.setCellStyle(getTittlesStyle(wb));
						cellSkills.setCellValue(prosAndCons.getEvaluator().getPerson().getName());

						cellSkills = rowSkills.createCell(1);
						cellSkills.setCellStyle(getDataStyle(wb));
						cellSkills.setCellValue(prosAndCons.getProject());
						
						cellSkills = rowSkills.createCell(2);
						cellSkills.setCellStyle(getDataStyle(wb));
						cellSkills.setCellType(1);
						if(prosAndCons.getPro()!= null){
							cellSkills.setCellValue(prosAndCons.getPro());
						} else {
							cellSkills.setCellValue(" ");	
						}
						cellSkills = rowSkills.createCell(3);
						cellSkills.setCellStyle(getDataStyle(wb));
						if (prosAndCons.getCon()!=null){
							cellSkills.setCellValue(prosAndCons.getCon());
						} else {
							cellSkills.setCellValue(" ");
						}	
						cellExtra = rowSkills.createCell(4);
						cellExtra.setCellStyle(getExtraStyle(wb));
						
						currentRow++;
					}
					currentRow++;
					extraRow = sheet.createRow(currentRow-1);
					cellExtra = extraRow.createCell(0);
					cellExtra.setCellStyle(getExtraStyle(wb));
					cellExtra = extraRow.createCell(1);
					cellExtra.setCellStyle(getExtraStyle(wb));
					cellExtra = extraRow.createCell(2);
					cellExtra.setCellStyle(getExtraStyle(wb));
					cellExtra = extraRow.createCell(3);
					cellExtra.setCellStyle(getExtraStyle(wb));
					cellExtra = extraRow.createCell(4);
					cellExtra.setCellStyle(getExtraStyle(wb));
					
					
			}
	    	extraRow = sheet.createRow(currentRow);
			cellExtra = extraRow.createCell(0);
			cellExtra.setCellStyle(getExtraStyle(wb));
			cellExtra = extraRow.createCell(1);
			cellExtra.setCellStyle(getExtraStyle(wb));
			cellExtra = extraRow.createCell(2);
			cellExtra.setCellStyle(getExtraStyle(wb));
			cellExtra = extraRow.createCell(3);
			cellExtra.setCellStyle(getExtraStyle(wb));
			cellExtra = extraRow.createCell(4);
			cellExtra.setCellStyle(getExtraStyle(wb));
	    	Row rowFooter = sheet.createRow(currentRow+1);
			
			Cell cellT = rowFooter.createCell(0);
	    	cellT.setCellStyle(getDataStyle(wb));
	    	cellT.setCellValue("Evalautor ");
	    	
	    	cellT = rowFooter.createCell(1);
	    	cellT.setCellStyle(getTittlesStyle(wb));
	    	cellT.setCellValue("Project ");
	    	
	    	cellT = rowFooter.createCell(2);
	    	cellT.setCellStyle(getTittlesStyle(wb));
	    	cellT.setCellValue("Score ");
	    	
	    	cellT = rowFooter.createCell(3);
	    	cellT.setCellStyle(getTittlesStyle(wb));
	    	cellT.setCellValue("Effort  ");		
	    	
	    	cellExtra = rowFooter.createCell(4);
			cellExtra.setCellStyle(getExtraStyle(wb));
			
	    	currentRow += 1;
	    	
	    	for (FeedbackMentorEffortScore feedbackMentorEffortScore : feedbackPeriodMentorReport.getFeedbackMentorEffortScore()) {
	    		rowFooter = sheet.createRow(currentRow+1);
	    		Cell cellFBF = rowFooter.createCell(0);
	    		cellFBF.setCellStyle(getTittlesStyle(wb));
	    		cellFBF.setCellValue(feedbackMentorEffortScore.getEvaluator().getPerson().getName());
	    		
	    		cellFBF = rowFooter.createCell(1);
	    		cellFBF.setCellStyle(getDataStyle(wb));
	    		cellFBF.setCellValue(feedbackMentorEffortScore.getProject());
	    		
	    		cellFBF = rowFooter.createCell(2);
	    		cellFBF.setCellStyle(getDataStyle(wb));
	    		try {
		    	cellFBF.setCellValue(feedbackMentorEffortScore.getEffort().getScoreType().toString());
	    		} catch (Exception e) {
				}

		    	cellFBF = rowFooter.createCell(3);
		    	cellFBF.setCellStyle(getDataStyle(wb));
		    	try {
		    		cellFBF.setCellValue(feedbackMentorEffortScore.getEffort().getJustification());
				} catch (Exception e) {
				}

				cellFBF = rowFooter.createCell(4);
		    	cellFBF.setCellStyle(getDataStyle(wb));
		    	try {
		    		cellFBF.setCellValue(feedbackMentorEffortScore.getScoreType().name());	
				} catch (Exception e) {
				}
				currentRow++;
			}
	    	
	    	extraRow = sheet.createRow(currentRow+1);
			cellExtra = extraRow.createCell(0);
			cellExtra.setCellStyle(getExtraStyle(wb));
			cellExtra = extraRow.createCell(1);
			cellExtra.setCellStyle(getExtraStyle(wb));
			cellExtra = extraRow.createCell(2);
			cellExtra.setCellStyle(getExtraStyle(wb));
			cellExtra = extraRow.createCell(3);
			cellExtra.setCellStyle(getExtraStyle(wb));
			cellExtra = extraRow.createCell(4);
			cellExtra.setCellStyle(getExtraStyle(wb));
	    	
	    	currentRow+=2;
	    }
	    ByteArrayOutputStream baos = new ByteArrayOutputStream();
	    wb.write(baos);
	    excelStream = new ByteArrayInputStream(baos.toByteArray());
	    fileName = "Mentors Report.xlsx";
	    
	    baos.close();
	    
	return EXCEL;
    }

    /**
     * Devuelve el estilo para las celdas que van en los titulos.
     * 
     * @param wb
     * @return
     */
    public XSSFCellStyle getTittlesStyle(final XSSFWorkbook wb) {
        XSSFCellStyle style = wb.createCellStyle();
        style.setBorderTop((short) 1);
        style.setBorderBottom((short) 1);
        style.setBorderLeft((short) 1);
        style.setBorderRight((short) 1);
        style.setFillForegroundColor(new XSSFColor(new Color(146, 208, 80)));
        style.setFillPattern(style.SOLID_FOREGROUND);

        XSSFFont font = wb.createFont();
        font.setFontName("Calibri");
        font.setBold(true);
        font.setItalic(true);
        style.setFont(font);
        return style;
    }

    /**
     * Desvuelve el estilo para las celdas con datos en los encabezados
     * 
     * @param wb
     * @return
     */
    public XSSFCellStyle getHeadersStyle(final XSSFWorkbook wb) {
        XSSFCellStyle style = wb.createCellStyle();
        style.setBorderTop((short) 1);
        style.setBorderBottom((short) 1);
        style.setBorderLeft((short) 1);
        style.setBorderRight((short) 1);
        style.setFillForegroundColor(new XSSFColor(new Color(197, 217, 241)));
        style.setFillPattern(style.SOLID_FOREGROUND);

        XSSFFont font = wb.createFont();
        font.setFontName("Calibri");
        font.setBold(true);
        style.setFont(font);
        return style;
    }

    /**
     * Devuelve el estilo para las celdas donde se cargan los datos generales.
     * 
     * @param wb
     * @return
     */
    public XSSFCellStyle getDataStyle(final XSSFWorkbook wb) {
        XSSFCellStyle style = wb.createCellStyle();
        style.setBorderTop((short) 1);
        style.setBorderBottom((short) 1);
        style.setBorderLeft((short) 1);
        style.setBorderRight((short) 1);
        style.setFillForegroundColor(new XSSFColor(new Color(234, 241, 221)));
        style.setFillPattern(style.SOLID_FOREGROUND);

        return style;
    }

    /**
     * Genera estilo para las celdas de relleno visual.
     * 
     * @param wb
     * @return
     */
    public XSSFCellStyle getExtraStyle(final XSSFWorkbook wb) {
        XSSFCellStyle style = wb.createCellStyle();
        style.setFillForegroundColor(new XSSFColor(new Color(215, 228, 188)));
        style.setFillPattern(style.SOLID_FOREGROUND);

        return style;
    }

    /**
     * Devuelve la lista necesaria para generar el listado de mentorados.
     * 
     * Retorna error en el caso de que no se haya seleccionado un mentor, o un
     * dato valido.
     * 
     * @return
     */
    public String filter() {
        if (getSelectedMentorName() != null && !getSelectedMentorName().trim().equals("")) {
            Employee mentor = mentoringService.searchById(getSelectedMentorId());

            if (mentor == null) {
                addActionError("There is no Mentor with that name");
                return INPUT;
            }

            mentorsReportList = feedbackPeriodService.getMentorsReport(mentor.getPerson(), getPeriodId());
        } else {
            addActionError("The field Mentor cannot be empty");
            return INPUT;
        }
        return SUCCESS;
    }

    /**
     * Genera una lista con las evaluaciones de cada uno de los mentorados, para
     * una mentor dado.
     * 
     * @return
     */
    public Collection<FeedbackPeriodMentorReport> getMentorsReportList() {
        return mentorsReportList = feedbackPeriodService.getMentorsReport(
                mentoringService.searchById(getSelectedMentorId()).getPerson(), getPeriodId());
    }

    public List<Employee> getAllMentorsList() {
        return (List<Employee>) mentoringService.getAllActiveMentors();
    }

    public String getContentDisposition() {
        return "attachment;filename= " + fileName;
    }

    // Getters y Setters Service
    public FeedbackPeriodService getFeedbackPeriodService() {
        return feedbackPeriodService;
    }

    public void setFeedbackPeriodService(final FeedbackPeriodService feedbackPeriodService) {
        this.feedbackPeriodService = feedbackPeriodService;
    }

    public PeriodService getPeriodService() {
        return periodService;
    }

    public void setPeriodService(final PeriodService periodService) {
        this.periodService = periodService;
    }

    public MentoringService getMentoringService() {
        return mentoringService;
    }

    public void setMentoringService(final MentoringService mentoringService) {
        this.mentoringService = mentoringService;
    }

    // Getters y Setters properties
    public String getPeriodId() {
        return periodId;
    }

    public void setPeriodId(final String period) {
        periodId = period;
    }

    public long getSelectedMentorId() {
        return selectedMentorId;
    }

    public void setSelectedMentorId(final long selectedMentorId) {
        this.selectedMentorId = selectedMentorId;
    }

    public String getSelectedMentorName() {
        return selectedMentorName;
    }

    public void setSelectedMentorName(final String selectedMentorName) {
        this.selectedMentorName = selectedMentorName;
    }

    public InputStream getAutoevaluationStream() {
        return autoevaluationStream;
    }

    public void setAutoevaluationStream(final InputStream autoevaluationStream) {
        this.autoevaluationStream = autoevaluationStream;
    }

    public InputStream getExcelStream() {
        return excelStream;
    }

    public void setExcelStream(final InputStream excelStream) {
        this.excelStream = excelStream;
    }

    public String getFileName() {
        return fileName;
    }

    public void setFileName(final String fileName) {
        this.fileName = fileName;
    }

    @Override
    public void setSession(final Map<String, Object> session) {
        this.session = session;
    }

    public Map<String, Object> getSession() {
        return session;
    }

    public void setUser(final Person user) {
        this.user = user;
    }

    public Person getUser() {
        return CoreServiceLocator.getUserAuthService().getAuthorizedPerson(getSession());
    }

    /*
     * (non-Javadoc)
     * 
     * @see
     * org.apache.struts2.interceptor.ServletRequestAware#setServletRequest(
     * javax.servlet.http.HttpServletRequest)
     */
    @Override
    public void setServletRequest(final HttpServletRequest request) {
        this.request = request;
    }

    /**
     * @return the request
     */
    public HttpServletRequest getRequest() {
        return request;
    }

    /**
     * @return the showReturn
     */
    public boolean isShowReturn() {
        String permission = PermissionName.MANAGE_FEEBACKS.toString();
        return permissionChecker.hasPermission(permission, request.getSession());
    }

}
